bitkeeper revision 1.1108.28.1 (4106e7efzfLYJJxhDUfFLjrg1-JKEw)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Tue, 27 Jul 2004 23:40:31 +0000 (23:40 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Tue, 27 Jul 2004 23:40:31 +0000 (23:40 +0000)
Finish merge of old domain allocation code with tehe buddy-allocator system.
Now just needs exporting to priv guest OSes so they can allocate multi-page
physmem chunks. Then to fix Linux's pci_alloc_consistent().

xen/arch/x86/domain.c
xen/arch/x86/shadow.c
xen/common/dom_mem_ops.c
xen/common/domain.c
xen/common/page_alloc.c
xen/include/asm-x86/mm.h
xen/include/xen/mm.h

index 73a838d6fba766e48080f9fef3f047c10c987349..6f6b7b620f9a7f639badadbd926ac0911f466899 100644 (file)
@@ -476,7 +476,7 @@ void domain_relinquish_memory(struct domain *d)
         put_page(page);
 
     /* Relinquish all pages on the domain's allocation list. */
-    spin_lock_recursive(&d->page_alloc_lock); /* may enter free_domain_page */
+    spin_lock_recursive(&d->page_alloc_lock); /* may enter free_domheap_page */
     list_for_each_safe ( ent, tmp, &d->page_list )
     {
         page = list_entry(ent, struct pfn_info, list);
index a98cf3076cef7f22e246af4c9892a1cabbf844b9..362b0f4560aafb4e3e9f77ecd419c8aecf53fd90 100644 (file)
@@ -512,7 +512,7 @@ int shadow_mode_control(struct domain *d, dom0_shadow_control_t *sc)
 static inline struct pfn_info *alloc_shadow_page(struct mm_struct *m)
 {
     m->shadow_page_count++;
-    return alloc_domheap_page();
+    return alloc_domheap_page(NULL);
 }
 
 void unshadow_table( unsigned long gpfn, unsigned int type )
index 864ea3a4c17e5d93de1334209c6b2048052337ee..240eb60086cdcadc688c223dd57e59d8ed13f314 100644 (file)
@@ -24,7 +24,7 @@ static long alloc_dom_mem(struct domain *d,
 
     for ( i = 0; i < nr_pages; i++ )
     {
-        if ( unlikely((page = alloc_domain_page(d)) == NULL) )
+        if ( unlikely((page = alloc_domheap_page(d)) == NULL) )
         {
             DPRINTK("Could not allocate a frame\n");
             break;
index 888c88f9837b5b7157207951f165b664012abb5e..8f12c624a8c6c1be26bcce3a936ba21e1e849d76 100644 (file)
@@ -15,7 +15,6 @@
 #include <xen/console.h>
 #include <asm/shadow.h>
 #include <hypervisor-ifs/dom0_ops.h>
-#include <asm/hardirq.h>
 #include <asm/domain_page.h>
 
 /* Both these structures are protected by the tasklist_lock. */
@@ -194,97 +193,6 @@ void domain_shutdown(u8 reason)
     __enter_scheduler();
 }
 
-struct pfn_info *alloc_domain_page(struct domain *d)
-{
-    struct pfn_info *page = NULL;
-    unsigned long mask, pfn_stamp, cpu_stamp;
-    int i;
-
-    ASSERT(!in_irq());
-
-    page = alloc_domheap_page();
-    if ( unlikely(page == NULL) )
-        return NULL;
-
-    if ( (mask = page->u.free.cpu_mask) != 0 )
-    {
-        pfn_stamp = page->tlbflush_timestamp;
-        for ( i = 0; (mask != 0) && (i < smp_num_cpus); i++ )
-        {
-            if ( mask & (1<<i) )
-            {
-                cpu_stamp = tlbflush_time[i];
-                if ( !NEED_FLUSH(cpu_stamp, pfn_stamp) )
-                    mask &= ~(1<<i);
-            }
-        }
-
-        if ( unlikely(mask != 0) )
-        {
-            flush_tlb_mask(mask);
-            perfc_incrc(need_flush_tlb_flush);
-        }
-    }
-
-    page->u.inuse.domain = d;
-    page->u.inuse.type_info = 0;
-    if ( d != NULL )
-    {
-        wmb(); /* Domain pointer must be visible before updating refcnt. */
-        spin_lock(&d->page_alloc_lock);
-        if ( unlikely(d->tot_pages >= d->max_pages) )
-        {
-            DPRINTK("Over-allocation for domain %u: %u >= %u\n",
-                    d->domain, d->tot_pages, d->max_pages);
-            spin_unlock(&d->page_alloc_lock);
-            page->u.inuse.domain = NULL;
-            goto free_and_exit;
-        }
-        list_add_tail(&page->list, &d->page_list);
-        page->u.inuse.count_info = PGC_allocated | 1;
-        if ( unlikely(d->tot_pages++ == 0) )
-            get_domain(d);
-        spin_unlock(&d->page_alloc_lock);
-    }
-
-    return page;
-
- free_and_exit:
-    free_domheap_page(page);
-    return NULL;
-}
-
-void free_domain_page(struct pfn_info *page)
-{
-    int            drop_dom_ref;
-    struct domain *d = page->u.inuse.domain;
-
-    if ( unlikely(IS_XEN_HEAP_FRAME(page)) )
-    {
-        spin_lock_recursive(&d->page_alloc_lock);
-        drop_dom_ref = (--d->xenheap_pages == 0);
-        spin_unlock_recursive(&d->page_alloc_lock);
-    }
-    else
-    {
-        page->tlbflush_timestamp = tlbflush_clock;
-        page->u.free.cpu_mask = 1 << d->processor;
-        
-        /* NB. May recursively lock from domain_relinquish_memory(). */
-        spin_lock_recursive(&d->page_alloc_lock);
-        list_del(&page->list);
-        drop_dom_ref = (--d->tot_pages == 0);
-        spin_unlock_recursive(&d->page_alloc_lock);
-
-        page->u.inuse.count_info = 0;
-        
-        free_domheap_page(page);
-    }
-
-    if ( drop_dom_ref )
-        put_domain(d);
-}
-
 unsigned int alloc_new_dom_mem(struct domain *d, unsigned int kbytes)
 {
     unsigned int alloc_pfns, nr_pages;
@@ -296,7 +204,7 @@ unsigned int alloc_new_dom_mem(struct domain *d, unsigned int kbytes)
     /* Grow the allocation if necessary. */
     for ( alloc_pfns = d->tot_pages; alloc_pfns < nr_pages; alloc_pfns++ )
     {
-        if ( unlikely((page=alloc_domain_page(d)) == NULL) )
+        if ( unlikely((page = alloc_domheap_page(d)) == NULL) )
         {
             domain_relinquish_memory(d);
             return -ENOMEM;
index 065f85088d652c8d3a905102d36278290ada6823..bc78bb266d0ac7fbd62921f3a7d2c99e5223076c 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/page.h>
 #include <xen/spinlock.h>
 #include <xen/slab.h>
+#include <xen/irq.h>
 
 
 /*********************
@@ -198,6 +199,9 @@ struct pfn_info *alloc_heap_pages(int zone, int order)
     struct pfn_info *pg;
     unsigned long flags;
 
+    if ( unlikely(order < MIN_ORDER) || unlikely(order > MAX_ORDER) )
+        return NULL;
+
     spin_lock_irqsave(&heap_lock, flags);
 
     /* Find smallest order which can satisfy the request. */
@@ -331,18 +335,116 @@ void init_domheap_pages(unsigned long ps, unsigned long pe)
     init_heap_pages(MEMZONE_DOM, phys_to_page(ps), (pe - ps) >> PAGE_SHIFT);
 }
 
-struct pfn_info *alloc_domheap_pages(int order)
+struct pfn_info *alloc_domheap_pages(struct domain *d, int order)
 {
-    struct pfn_info *pg = alloc_heap_pages(MEMZONE_DOM, order);
+    struct pfn_info *pg;
+    unsigned long mask, flushed_mask, pfn_stamp, cpu_stamp;
+    int i;
+
+    ASSERT(!in_irq());
+
+    if ( unlikely((pg = alloc_heap_pages(MEMZONE_DOM, order)) == NULL) )
+        return NULL;
+
+    flushed_mask = 0;
+    for ( i = 0; i < (1 << order); i++ )
+    {
+        pg[i].u.inuse.domain    = NULL;
+        pg[i].u.inuse.type_info = 0;
+
+        if ( (mask = (pg[i].u.free.cpu_mask & ~flushed_mask)) != 0 )
+        {
+            pfn_stamp = pg[i].tlbflush_timestamp;
+            for ( i = 0; (mask != 0) && (i < smp_num_cpus); i++ )
+            {
+                if ( mask & (1<<i) )
+                {
+                    cpu_stamp = tlbflush_time[i];
+                    if ( !NEED_FLUSH(cpu_stamp, pfn_stamp) )
+                        mask &= ~(1<<i);
+                }
+            }
+            
+            if ( unlikely(mask != 0) )
+            {
+                flush_tlb_mask(mask);
+                perfc_incrc(need_flush_tlb_flush);
+                flushed_mask |= mask;
+            }
+        }
+    }
+
+    if ( d == NULL )
+        return pg;
+
+    spin_lock(&d->page_alloc_lock);
+
+    if ( unlikely((d->tot_pages + (1 << order)) > d->max_pages) )
+    {
+        DPRINTK("Over-allocation for domain %u: %u > %u\n",
+                d->domain, d->tot_pages + (1 << order), d->max_pages);
+        spin_unlock(&d->page_alloc_lock);
+        free_heap_pages(MEMZONE_DOM, pg, order);
+        return NULL;
+    }
+
+    if ( unlikely(d->tot_pages == 0) )
+        get_domain(d);
+
+    d->tot_pages += 1 << order;
+
+    for ( i = 0; i < (1 << order); i++ )
+    {
+        pg[i].u.inuse.domain = d;
+        wmb(); /* Domain pointer must be visible before updating refcnt. */
+        pg->u.inuse.count_info = PGC_allocated | 1;
+        list_add_tail(&pg->list, &d->page_list);
+    }
+
+    spin_unlock(&d->page_alloc_lock);
+    
     return pg;
 }
 
 void free_domheap_pages(struct pfn_info *pg, int order)
 {
-    free_heap_pages(MEMZONE_DOM, pg, order);
+    int            i, drop_dom_ref;
+    struct domain *d = pg->u.inuse.domain;
+
+    if ( unlikely(IS_XEN_HEAP_FRAME(pg)) )
+    {
+        spin_lock_recursive(&d->page_alloc_lock);
+        d->xenheap_pages -= 1 << order;
+        drop_dom_ref = (d->xenheap_pages == 0);
+        spin_unlock_recursive(&d->page_alloc_lock);
+    }
+    else
+    {
+        /* NB. May recursively lock from domain_relinquish_memory(). */
+        spin_lock_recursive(&d->page_alloc_lock);
+
+        for ( i = 0; i < (1 << order); i++ )
+        {
+            pg[i].tlbflush_timestamp = tlbflush_clock;
+            pg[i].u.inuse.count_info = 0;
+            pg[i].u.free.cpu_mask    = 1 << d->processor;
+            list_del(&pg[i].list);
+        }
+
+        d->tot_pages -= 1 << order;
+        drop_dom_ref = (d->tot_pages == 0);
+
+        spin_unlock_recursive(&d->page_alloc_lock);
+
+        free_heap_pages(MEMZONE_DOM, pg, order);
+    }
+
+    if ( drop_dom_ref )
+        put_domain(d);
 }
 
 unsigned long avail_domheap_pages(void)
 {
     return avail[MEMZONE_DOM];
 }
+
index 7f9c57cf62d3c7218cd454e8b7ee152c8c2a2122..35ad6ea7c921b2ea6867daa24a15311e97f3e54e 100644 (file)
@@ -114,9 +114,6 @@ extern unsigned long frame_table_size;
 extern unsigned long max_page;
 void init_frametable(void *frametable_vstart, unsigned long nr_pages);
 
-struct pfn_info *alloc_domain_page(struct domain *d);
-void free_domain_page(struct pfn_info *page);
-
 int alloc_page_type(struct pfn_info *page, unsigned int type);
 void free_page_type(struct pfn_info *page, unsigned int type);
 
@@ -131,7 +128,7 @@ static inline void put_page(struct pfn_info *page)
     while ( unlikely((y = cmpxchg(&page->u.inuse.count_info, x, nx)) != x) );
 
     if ( unlikely((nx & PGC_count_mask) == 0) )
-        free_domain_page(page);
+        free_domheap_page(page);
 }
 
 
index 7133af933dbdaba4967bc5f4bee9fbc03cc7129e..859db7c9f1851332f157af0b98376bc7c8a5d00b 100644 (file)
@@ -2,7 +2,8 @@
 #ifndef __XEN_MM_H__
 #define __XEN_MM_H__
 
-#include <asm/mm.h>
+struct domain;
+struct pfn_info;
 
 /* Generic allocator */
 unsigned long init_heap_allocator(
@@ -20,10 +21,12 @@ void free_xenheap_pages(unsigned long p, int order);
 
 /* Domain suballocator */
 void init_domheap_pages(unsigned long ps, unsigned long pe);
-struct pfn_info *alloc_domheap_pages(int order);
+struct pfn_info *alloc_domheap_pages(struct domain *d, int order);
 void free_domheap_pages(struct pfn_info *pg, int order);
 unsigned long avail_domheap_pages(void);
-#define alloc_domheap_page() (alloc_domheap_pages(0))
+#define alloc_domheap_page(_d) (alloc_domheap_pages(_d,0))
 #define free_domheap_page(_p) (free_domheap_pages(_p,0))
 
+#include <asm/mm.h>
+
 #endif /* __XEN_MM_H__ */